package cn.gyx.hrm.service.impl;

import cn.gyx.hrm.config.HighlightResultMapper;
import cn.gyx.hrm.doc.CourseDoc;
import cn.gyx.hrm.doc.dto.CourseSearchDto;
import cn.gyx.hrm.repository.CourseElasticSearchRepository;
import cn.gyx.hrm.service.ICourseESService;
import cn.gyx.hrm.util.PageList;
import cn.gyx.hrm.vo.AggPageList;
import cn.gyx.hrm.vo.TermsAggBucket;
import com.netflix.discovery.converters.Auto;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import java.security.Key;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class CourseESServiceImpl implements ICourseESService {

    @Autowired
    private CourseElasticSearchRepository repository;

    @Autowired
    private ElasticsearchTemplate template;

    @Autowired
    private HighlightResultMapper resultMapper;

    @Override
    public void save(CourseDoc doc) {
        repository.save(doc);
    }

    @Override
    public void deleteById(Long id) {
        repository.deleteById(id);
    }

    @Override
    public PageList<CourseDoc> search(CourseSearchDto dto) {
         NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();

        //排序
        // 先判断传入数据是否有值,降序排列
        if(!StringUtils.isEmpty(dto.getSortField())){
            String sortField = "onlineTime";
            switch (sortField.toLowerCase()){
                case "xl" :sortField = "saleCount"; break;
                case "xp" :sortField = "onlineTime";break;
                case "pl" :sortField = "commentCount";break;
                case "jg" :sortField = "price";break;
                case "rq" :sortField = "viewCount";break;
            }
            SortOrder sortOrder = SortOrder.DESC;// 默认设置为降序排列
            // 判断排序是否为空
            if (dto.getSortType() != null && dto.getSortType().equalsIgnoreCase("asc")){
                sortOrder = SortOrder.ASC;
            }
            searchQueryBuilder.withSort(SortBuilders.fieldSort(sortField).order(sortOrder));
        }

        //============================分页==================================
        searchQueryBuilder.withPageable(PageRequest.of(dto.getPage() - 1, dto.getRows()));

        //===========================条件===================================
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        // 添加must
        if (!StringUtils.isEmpty(dto.getKeyword())){
            boolQuery.must(QueryBuilders.matchQuery("name", dto.getKeyword()));
        }

        // 添加filter
//        boolQuery.filter();

        // 判断课程分类id
        if(dto.getCourseTypeId() !=null ) {
            boolQuery.filter(QueryBuilders.termQuery("courseTypeId", dto.getCourseTypeId()));
        }

        // 等级名字
        if (!StringUtils.isEmpty(dto.getGradeName())){
            boolQuery.filter(QueryBuilders.termQuery("gradeName",dto.getGradeName() ));
        }

        // 机构名字
        if (!StringUtils.isEmpty(dto.getTenantName())){
            boolQuery.filter(QueryBuilders.termQuery("tenantName", dto.getTenantName()));
        }

        // 价格范围(最大值)
        if (dto.getPriceMax() != null) {
            boolQuery.filter(QueryBuilders.rangeQuery("price").lte(dto.getPriceMax()));
        }
        // 价格范围（最小值）
        if (dto.getPriceMin() != null) {
            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(dto.getPriceMin()));
        }
        searchQueryBuilder.withQuery(boolQuery);

        // ==========================高亮============================
        // 对用es搜索出来的关键字进行高亮操作 设置颜色为绿色
        HighlightBuilder.Field fields = new HighlightBuilder.Field("name")
                .preTags("<span style = 'color:red'>")
                .postTags("</span>");
        searchQueryBuilder.withHighlightFields(fields);
        // ========================聚合=============================
        TermsAggregationBuilder greadTermName = AggregationBuilders.terms("greadTermName").field("gradeName");
        TermsAggregationBuilder tenantTermName = AggregationBuilders.terms("tenantTermName").field("tenantName");
        searchQueryBuilder.addAggregation(greadTermName).addAggregation(tenantTermName);

        //=======================处理结果===========================
        AggregatedPage<CourseDoc> page = template.queryForPage(searchQueryBuilder.build(), CourseDoc.class, resultMapper);
//        Page<CourseDoc> page = repository.search(searchQueryBuilder.build());

        Map<String,List<TermsAggBucket>> termsAggBucket = new HashMap<>();

        // 拿到聚合方法stringAggregationMap 将机构名字和等级名字聚合
        Map<String, Aggregation> stringAggregationMap = page.getAggregations().asMap();

        stringAggregationMap.keySet().forEach(key->{// 这里的key是聚合的名字
            // 新建Buck列表
            List<TermsAggBucket> termsAggBuckets = new ArrayList<>();

            StringTerms aggregation = (StringTerms)stringAggregationMap.get(key);
            aggregation.getBuckets().forEach(bucket -> {
                // 拿到名字
                String name = bucket.getKey().toString();
                // 拿到值
                long docCount = bucket.getDocCount();

                // 将bucket转换为TermsAggBucket
                TermsAggBucket aggBucket = new TermsAggBucket(name,docCount);
                termsAggBuckets.add(aggBucket);
            });
            // 加入聚合中
            termsAggBucket.put(key,termsAggBuckets );
        });

        return new AggPageList(page.getTotalElements(),page.getContent(),termsAggBucket);
    }

}